package com.betterjr.modules.customer.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.betterjr.common.data.SimpleDataEntity;
import com.betterjr.common.utils.BTAssert;
import com.betterjr.common.utils.BetterDateUtils;
import com.betterjr.common.utils.Collections3;
import com.betterjr.common.utils.QueryTermBuilder;
import com.betterjr.common.utils.UserUtils;
import com.betterjr.mapper.pagehelper.Page;
import com.betterjr.modules.account.entity.CustInfo;
import com.betterjr.modules.account.service.CustAccountService;
import com.betterjr.modules.customer.AbstractBaseMechCustTemDataHandlerAdapter;
import com.betterjr.modules.customer.dao.CustMechBankAccountMapper;
import com.betterjr.modules.customer.entity.CustMechBankAccount;
import com.betterjr.modules.customer.entity.CustMechBankAccountTmp;
import com.betterjr.modules.customer.entity.SysNapsBankCode;
import com.betterjr.modules.document.service.CustFileItemService;
import com.betterjr.modules.temhandler.data.TemDataConstant;
import com.betterjr.modules.temhandler.entity.TemData;
import com.betterjr.modules.temhandler.entity.TemDataBuilder;
import com.betterjr.modules.temhandler.service.TemDataService;
import com.betterjr.modules.util.BetterBeanUtils;

/**
 *
 * @author liuwlBaseService<CustMechBankAccountMapper, CustMechBankAccount>
 *
 */
@Service
public class CustMechBankAccountService
        extends AbstractBaseMechCustTemDataHandlerAdapter<CustMechBankAccountMapper, CustMechBankAccount> {
    @Resource
    private CustAccountService accountService;

    @Resource
    private CustMechBankAccountTmpService bankAccountTmpService;

    @Resource
    private CustFileItemService fileItemService;

    @Autowired
    private TemDataService temDataService;

    @Autowired
    private SysNapsBankCodeService bankCodeService;

    @Autowired
    private CustAccountService custAccountService;

    /**
     * 查询银行账户列表
     * @param anCustNo
     * @return
     */
    public List<CustMechBankAccount> queryCustMechBankAccount(final Long anCustNo) {
        BTAssert.notNull(anCustNo, "客户编号不允许为空！");

        return this.selectByProperty("custNo", anCustNo);
    }

    /**
     * 根据客户编号查询银行账户
     * @param anCustNo
     * @return
     */
    public List<CustMechBankAccount> queryCustMechBankAccountByCustNo(final Long anCustNo) {
        if (null == anCustNo || "".equals(anCustNo)) {
            return this.selectByProperty("custType", "0");
        } else {
            return this.selectByProperty("custNo", anCustNo);
        }
    }

    /**
     * 
     * @Title: queryAllBankInfo 
     * @Description: TODO(查询所有银行信息) 
     * @param @return 参数说明 
     * @return List<CustMechBankAccount> 返回类型 
     * @throws 
     * @author chenlq
     * @date 2018年7月7日 下午4:20:04
     */
    public Page<List<CustMechBankAccount>> queryAllBankInfo(String flag, int pageNum, int pageSize) {
        final List<CustMechBankAccount> resultList = new ArrayList<CustMechBankAccount>();

        // 银行分页查询
        final Page<CustMechBankAccount> recordList = this.selectPropertyByPage("businStatus", "0", pageNum, pageSize,
                "1".equals(flag));
        for (final CustMechBankAccount accountList : recordList) {
            resultList.add(accountList);
        }
        return Page.listToPage(resultList, pageNum, pageSize, recordList.getPages(), recordList.getStartRow(),
                recordList.getTotal());

    }

    /**
     * 查询银行跟账号用于下拉
     * @param anCustNo
     * @return
     */
    public List<SimpleDataEntity> querBankAccountKeyAndValue(final Long anCustNo) {
        final List<CustMechBankAccount> accountList = this.queryCustMechBankAccount(anCustNo);
        final List<SimpleDataEntity> result = new ArrayList<SimpleDataEntity>();
        for (final CustMechBankAccount account : accountList) {
            result.add(new SimpleDataEntity(account.getBankAcco() + "-" + account.getBankName(),
                    String.valueOf(account.getBankAcco())));
        }
        return result;
    }

    /**
     * 查询银行账户信息
     */
    public CustMechBankAccount findCustMechBankAccount(final Long anId) {
        BTAssert.notNull(anId, "银行账户编号不允许为空！");

        final CustMechBankAccount bankAccount = this.selectByPrimaryKey(anId);
        return bankAccount;
    }

    /**
     * 添加银行账户信息
     */
    public CustMechBankAccount addCustMechBankAccount(final CustMechBankAccountTmp anBankAccountTmp) {
        BTAssert.notNull(anBankAccountTmp, "银行账户流水信息不允许为空！");

        final CustMechBankAccount bankAccount = new CustMechBankAccount();
        bankAccount.initAddValue(anBankAccountTmp);

        this.insert(bankAccount);
        return bankAccount;
    }

    /**
     * 添加银行账户信息
     *
     * @param anBankAccount
     * @return
     */
    public CustMechBankAccount addCustMechBankAccount(final CustMechBankAccount anBankAccount, final Long anCustNo) {
        BTAssert.notNull(anBankAccount, "银行账户信息不允许为空！");
        BTAssert.notNull(anCustNo, "客户编号不允许为空！");

        final CustInfo custInfo = accountService.selectByPrimaryKey(anCustNo);
        anBankAccount.initAddValue(anCustNo, custInfo.getCustName(), custInfo.getRegOperId(), custInfo.getRegOperName(),
                custInfo.getOperOrg());
        this.insert(anBankAccount);

        bankAccountTmpService.addCustMechBankAccountTmp(anBankAccount);
        return anBankAccount;
    }

    /**
     * 保存银行账户信息
     */
    public CustMechBankAccount saveCustMechBankAccount(final CustMechBankAccount anBankAccount, final Long anId) {
        BTAssert.notNull(anId, "银行账户编号不允许为空！");
        BTAssert.notNull(anBankAccount, "银行账户信息不允许为空！");

        final CustMechBankAccount tempBankAccount = this.selectByPrimaryKey(anId);
        BTAssert.notNull(tempBankAccount, "对应的银行账户信息没有找到！");

        tempBankAccount.initModifyValue(anBankAccount);
        this.updateByPrimaryKeySelective(tempBankAccount);
        return tempBankAccount;
    }

    /**
     * 通过银行账户流水修改银行账户
     */
    public CustMechBankAccount saveCustMechBankAccount(final CustMechBankAccountTmp anBankAccountTmp) {
        BTAssert.notNull(anBankAccountTmp, "银行账户流水编号不允许为空！");

        final CustMechBankAccount tempBankAccount = this.selectByPrimaryKey(anBankAccountTmp.getRefId());
        BTAssert.notNull(tempBankAccount, "对应的银行账户信息没有找到！");

        tempBankAccount.initModifyValue(anBankAccountTmp);
        this.updateByPrimaryKeySelective(tempBankAccount);
        return tempBankAccount;
    }

    /**
     * @param anCustNo
     * @return
     */
    public CustMechBankAccount findDefaultCustMechBankAccount(final Long anCustNo) {
        BTAssert.notNull(anCustNo, "公司编号不允许为空！");

        final Map<String, Object> conditionMap = new HashMap<>();
        conditionMap.put("custNo", anCustNo);
        // conditionMap.put("isDefault", true);
        return Collections3.getFirst(this.selectByProperty(conditionMap, "isDefault desc"));
    }

    /**
     * @param anTmpAcco
     * @param anTmpAccoName
     * @return
     */
    public CustMechBankAccount findCustMechBankAccount(final String anBankAcco, final String anBankAccoName) {
        final Map<String, Object> conditionMap = new HashMap<>();
        conditionMap.put("bankAcco", anBankAcco);
        conditionMap.put("bankAccoName", anBankAccoName);
        return Collections3.getFirst(this.selectByProperty(conditionMap));
    }

    /**
     * @param anTmpAcco
     * @return
     */
    public CustMechBankAccount findBankAccountByAcco(final String anBankAcco) {
        final Map<String, Object> conditionMap = new HashMap<>();
        conditionMap.put("bankAcco", anBankAcco);
        return Collections3.getFirst(this.selectByProperty(conditionMap));
    }

    @SuppressWarnings("unchecked")
    @Override
    public TemData saveAddOrUpdateTemData(final TemData anTemData) {
        // 插入校验
        final Map<String, Object> map = QueryTermBuilder.newInstance().put("custNo", anTemData.getCustNo()).build();
        final List<TemData> temDataList = temDataService.queryTemData(anTemData.getBusinTableType(), "1,2,3", map, "2",
                1, 10);
        BTAssert.isTrue(Collections3.isEmpty(temDataList), "已经有变更在申请过程中");
        return temDataService.saveAddTemData(anTemData);
    }

    public CustMechBankAccount saveAddCustMechBankAccountTmp(final CustMechBankAccount custMechBankAccount,
            final String anFileList) {

        BTAssert.notNull(custMechBankAccount, "公司基本信息-流水信息 不能为空！");
        BTAssert.notNull(custMechBankAccount.getCustNo(), "公司基本信息-流水信息 不能为空！");
        custMechBankAccount.saveAddInitValue(UserUtils.getOperatorInfo());
        custMechBankAccount
                .setBatchNo(fileItemService.updateCustFileItemInfo(anFileList, custMechBankAccount.getBatchNo()));
        final TemData anTemData = convertToTemData(custMechBankAccount);
        saveAddOrUpdateTemData(anTemData);
        return custMechBankAccount;
    }

    /*
     * 添加银行账户信息
     */
    /* public CustMechBankAccount saveAddCustMechBankAccount(Map<String, Object> anMap) {
        BTAssert.notNull(anMap.get("bankAccoName").toString(), "银行账户名不能为空！");
        BTAssert.notNull(anMap.get("bankAcco").toString(), "银行账户不能为空！");
        BTAssert.notNull(anMap.get("bankNo").toString(), "所属银行不能为空！");
        BTAssert.notNull(anMap.get("cityNo").toString(), "开户行所在地不能为空！");
        BTAssert.notNull(anMap.get("bankName").toString(), "开户银行全称不能为空！");
        BTAssert.notNull(anMap.get("custNo").toString(), "企业编号不能为空！");
        BTAssert.notNull(anMap.get("custName").toString(), "企业名称不能为空！");
    
        final String custNo = anMap.get("custNo").toString();
        final Long custNum = Long.parseLong(custNo);
        final CustInfo custInfo = custAccountService.selectByPrimaryKey(custNum);
        if (custInfo == null) {
            BTAssert.notNull(null, "没有对应的客户存在，后者客户编号输入不正确！");
        }
        anMap.put("custType", custInfo.getCustType());
        final CustMechBankAccount custMechBankAccount = associateBankInfo(anMap);
        custMechBankAccount.saveAddInitValue(UserUtils.getOperatorInfo());
    
        // 检查联行号不存在而银行全称正确情况，则可通过银行全称再获取一遍联行号
        final SysNapsBankCode bankCode = bankCodeService
                .findSysBankCodeInfoByBankName(anMap.get("bankName").toString());
        if (bankCode == null) {
            BTAssert.notNull(null, "银行全称输入不正确，你输入的银行不存在，请核准你的银行全称是否能在银行联行号中找到！");
        } else {
            custMechBankAccount.setPaySysNum(bankCode.getPaySysNum());
        }
    
        this.insert(custMechBankAccount);
        return custMechBankAccount;
    }*/

    public CustMechBankAccount saveAddCustMechBankAccount(final Map<String, Object> anMap) {
        final CustMechBankAccount bankInfo = new CustMechBankAccount();
        BetterBeanUtils.copyProperties2Bean(bankInfo, anMap);
        BTAssert.notNull(bankInfo.getBankAccoName(), "bankAccoName银行账户不能为空！");
        BTAssert.notNull(bankInfo.getBankAcco(), "bankAcco银行账号不能为空！");
        BTAssert.notNull(bankInfo.getBankName(), "bankName银行全称不能为空！");
        BTAssert.notNull(bankInfo.getCustNo(), "企业code不能为空！");

        // 银行帐号格式校验
        if (!Pattern.matches("\\d+", bankInfo.getBankAcco()) || bankInfo.getBankAcco().length() > 32) {
            BTAssert.notNull(null, "银行帐号格式不正确，请检查输入的帐号是否为不大于32位的数字！");
        }

        // 校验 重复 》》》》账号+企业
        final CustMechBankAccount tmpBank = new CustMechBankAccount();
        tmpBank.setBankAcco(bankInfo.getBankAcco());
        tmpBank.setCustNo(bankInfo.getCustNo());
        BTAssert.isNull(this.selectOne(tmpBank), "该企业的银行账号已经存在！");

        final SysNapsBankCode bankCode = bankCodeService.findSysBankCodeInfoByBankName(bankInfo.getBankName());
        BTAssert.notNull(bankCode, "银行全称输入不正确，不能获取对应的银行账户信息！");
        BTAssert.isTrue(StringUtils.isNotBlank(bankCode.getPaySysNum()), "银行全称对应的数据没有联行号！");

        bankInfo.setPaySysNum(bankCode.getPaySysNum());// TODO 多余字段，需要删除
        bankInfo.setBankBranch(bankCode.getPaySysNum());
        bankInfo.saveAddInitValue(UserUtils.getOperatorInfo());
        this.insert(bankInfo);
        return bankInfo;
    }

    /**
     * 关联银行信息
     * @param anMap
     * @return
     */
    public CustMechBankAccount associateBankInfo(final Map<String, Object> anMap) {
        final CustMechBankAccount bankInfo = new CustMechBankAccount();
        // 设置银行账户
        bankInfo.setBankAcco(anMap.get("bankAcco").toString());
        if (this.selectOne(bankInfo) != null) {
            BTAssert.notNull(null, "该银行账户已经存在！");
        }
        // 设置企业编号
        bankInfo.setCustNo(Long.parseLong(anMap.get("custNo").toString()));
        // 设置企业名称
        bankInfo.setCustName(anMap.get("custName").toString());
        // 设置银行账户名
        bankInfo.setBankAccoName(anMap.get("bankAccoName").toString());
        // 设置所属银行
        bankInfo.setBankNo(anMap.get("bankNo").toString());
        // 设置银行账户
        bankInfo.setBankAcco(anMap.get("bankAcco").toString());
        // 设置开户行所在地
        bankInfo.setCityNo(anMap.get("cityNo").toString());
        // 设置开户银行全称
        bankInfo.setBankName(anMap.get("custName").toString());
        // 设置企业类型
        bankInfo.setCustType(anMap.get("custType").toString());

        return bankInfo;
    }

    /*
     * 银行联行号查询
     */
    public SysNapsBankCode queryBankNumber(final String bankFullName) {
        return this.bankCodeService.findSysBankCodeInfoByBankName(bankFullName);
    }

    private TemData convertToTemData(final CustMechBankAccount custMechBankAccount) {
        final TemData anTemData = TemDataBuilder.newInstance()
                .businTableData(JSONObject.toJSONString(custMechBankAccount))
                .businTableId(custMechBankAccount.getId() + "").businTableOperorg(custMechBankAccount.getOperOrg())
                .businTableType(custMechBankAccount.getClass().getName()).laster(TemDataConstant.TEMDATA_LASTER_YES)
                .custNo(custMechBankAccount.getCustNo())
                .custName(accountService.selectByPrimaryKey(custMechBankAccount.getCustNo()).getCustName())
                .regDate(BetterDateUtils.getNumDate()).regOperid(UserUtils.getOperatorInfo().getId())
                .regOpername(UserUtils.getOperatorInfo().getName()).regTime(BetterDateUtils.getNumTime())
                .businStatus(TemDataConstant.TEMDATA_BUSINSTATUS_TEMTABLEINSERT).build();
        if (custMechBankAccount.getRefId() != null) {
            anTemData.setPrefixId(custMechBankAccount.getRefId());
        }
        return anTemData;
    }

}